#include "meshscenenode.h"
#include "game.h"

/**
 * Renderuje wezel sceny
 */
void MeshSceneNode::draw()
{
	SceneNode::draw();
	if(mesh)
	{
		Graphics* graphics = Game::getGraphics();

		if(getFlag() == SkyBox)
		{
			Matrix trans = getAbsoluteTransformation();
			trans.setTranslation(graphics->getCamera()->getReferenceNode()->
				getAbsoluteTransformation().getTranslation());
			graphics->setWorldTransformation(trans);
		}
		else
		{
			graphics->setWorldTransformation(getAbsoluteTransformation());
		}

		mesh->render(graphics->getDevice());

#if 0// _DEBUG
		BoundingBox box = boundingBox;
		box = getAbsoluteTransformation() * box;
		graphics->drawWireframeBox(box.getMinPoint(), box.getMaxPoint());
#endif
	}
}

/**
 * Odswierza macierz bezwzglednej transformacji
 */
void MeshSceneNode::refreshAbsoluteTransformation(bool recursive)
{
	SceneNode::refreshAbsoluteTransformation(recursive);

	if(mesh)
		boundingBox = getAbsoluteTransformation() * mesh->getBoundingBox();
	else
		boundingBox = getAbsoluteTransformation() * BoundingBox();
}

/**
 * Siatka
 */
void MeshSceneNode::setMesh(Mesh* m)
{
	if(mesh)
		mesh->release();
	mesh = m;
	if(mesh)
		mesh->addRef();
}

/**
 * Laduje wezel sceny i jego podwezly z danych pliku X.
 */
bool MeshSceneNode::loadFromXof(LPD3DXFILEDATA xofFileData)
{
	mesh = new Mesh();
	mesh->addRef();
	if(!mesh->loadFromXof(xofFileData))
	{
		mesh->release();
		mesh = NULL;
		return false;
	}
	boundingBox = mesh->getBoundingBox();
	return true;
}

/**
 * Sprawdza kolizje
 */
void MeshSceneNode::checkCollision(const BoundingBox &playerBox,
	float playerRadius, Physics::CollisionPacket &col) const
{
	//SceneNode::checkCollision(playerBox, playerRadius, col);
	if((flag == NoClip) || (flag == SkyBox) || (flag == Player))
		return;
	if(!mesh)
		return;

	const std::list<Triangle*>& triangles = mesh->getTriangles();
	Matrix transform = getAbsoluteTransformation();
	std::list<Triangle*>::const_iterator it;
	float invPlayerRadius = 1.0f / playerRadius;

	for(it = triangles.begin(); it != triangles.end(); it++)
	{

		const Vector* verts = (*it)->getVertices();
		Vector v[3];
		Triangle tri;

		/*Game::getGraphics()->drawWireframeBox(
			tri.getBoundingBox().getMinPoint(),
			tri.getBoundingBox().getMaxPoint());*/


		v[0] = transform * verts[0] * invPlayerRadius;
		v[1] = transform * verts[1] * invPlayerRadius;
		v[2] = transform * verts[2] * invPlayerRadius;

		tri = Triangle(v[2], v[1], v[0]);

		tri.recalculatePlane();
		tri.recalculateBoundingBox();
		tri.recalculateBoundingSphere();

		/*class Polygon poly;
		poly.getVertices().push_back(v[0]);
		poly.getVertices().push_back(v[1]);
		poly.getVertices().push_back(v[2]);
		poly.recalculatePlane();
		poly.recalculateBoundingBox();*/

		bool fc = col.foundCollision;
		col.foundCollision = false;

		Game::getPhysics()->checkTriangleCollision(tri, col);

		
		//Game::getPhysics()->checkPolygonCollision(poly, col);

		if(col.foundCollision)
		{
			v[0] = transform * verts[0];
			v[1] = transform * verts[1];
			v[2] = transform * verts[2];
			
			tri = Triangle(v[0], v[1], v[2]);
			tri.recalculatePlane();
			//tri.recalculateBoundingBox();
			Game::getGraphics()->drawWireframeTriangle(tri);
			

			//BoundingBox box = transform * (*it)->getBoundingBox();
			//Game::getGraphics()->drawWireframeBox(box.getMinPoint(), box.getMaxPoint());
			
		}
		else
			col.foundCollision = fc;
	}
}
